package com.moyun.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.moyun.common.utils.ObjectMapperUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @return
 * @Author yangboxuan
 * @Description
 * @Date 2021/6/2 14:24
 * @Param
 **/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    private static final Logger LOGGER = LoggerFactory.getLogger(RedisConfig.class);


    /**
     * @return org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>
     * @Author yangboxuan
     * @Description 指定RedisTemplate的序列化方式
     * @Date 2021/6/2 15:09
     * @Param [redisConnectionFactory]
     **/
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        /**
         * 获取 String类型序列化器
         * 使用 JSON类型序列化器
         */
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        RedisSerializer<Object> serializer = redisSerializer();
        // 指定reidsTemplate对象的序列化方式
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        /**
         * 使用 StringRedisSerializer 来序列化和反序列化redis的key值              ---->key采用String的序列化方式
         * 使用 Jackson2JsonRedisSerializer 来序列化和反序列化redis的value值      --->value采用json字符串的序列化方式
         */
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        redisTemplate.setHashValueSerializer(serializer);
        return redisTemplate;
    }

    /**
     * @return org.springframework.data.redis.serializer.RedisSerializer<java.lang.Object>
     * @Author yangboxuan
     * @Description 创建JSON序列化器
     * @Date 2021/6/2 14:45
     * @Param []
     **/
    @Bean
    public RedisSerializer<Object> redisSerializer() {
        // 使用Jackson2JsonRedisSerialize 替换默认序列化（备注，此处我用Object为例，各位看官请换成自己的类型哦~）
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        // 忽略未知的JSON字段  Jackson使用详解 https://juejin.cn/post/6844904166809157639#heading-18
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // Jackson序列化object时的一个坑 https://www.codeleading.com/article/12311513986/
        objectMapper.configure(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS, true);
        ObjectMapperUtils.registerTimeModule(objectMapper);
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }

}

